package com.wash.shoes.domain.order;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.common.utils.StringUtils;
import com.wash.shoes.common.enums.OrderStatusEnum;
import com.wash.shoes.domain.dto.BuyGoodsDto;
import com.wash.shoes.domain.dto.MobileOrderDto;
import com.wash.shoes.domain.dy.black.DyPreOrderDto;
import com.wash.shoes.domain.jd.JdOrderService;
import com.wash.shoes.domain.vo.RegionWashShopVo;
import com.wash.shoes.entity.*;
import com.wash.shoes.exception.WashException;
import com.wash.shoes.helper.FactoryAddressHelper;
import com.wash.shoes.resp.ShopAndFactoryPair;
import com.wash.shoes.service.*;
import com.wash.shoes.util.AddressCuttingUtil;
import com.wash.shoes.util.CodeUtil;
import com.wash.shoes.util.WashDateUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * @author lijianguo
 * @Date 25/03/2025 18:09 保存订单的,PC,小程序,美团,抖音,都应该在这里保存订单
 **/
@Log4j2
@Component
public class SaveOrderComponent {

    private final HashMap<String, String> provinceMap = new HashMap<>();
    @Resource
    OrderService orderService;
    @Resource
    ShopGoodsService shopGoodsService;
    @Resource
    CustomerService customerService;
    @Resource
    CustomerCouponService customerCouponService;
    @Resource
    ShopService shopService;
    @Resource
    OrderGoodService orderGoodService;
    @Resource
    JdOrderService jdOrderService;
    @Resource
    private CouponService couponService;
    @Resource
    private RegionDistributorService regionDistributorService;
    @Resource
    private RegionTransactionDetailService regionTransactionDetailService;
    @Resource
    private RegionWashShopService regionWashShopService;
    @Autowired
    private FactoryAreaConfigService factoryAreaConfigService;
    @Autowired
    private FactoryService factoryService;
    @Autowired
    private FactoryAddressHelper factoryAddressHelper;

    /**
     * 检查给定的字符串数组中的所有元素是否都以指定的前缀开始。
     *
     * @param goodsNames 要检查的字符串数组
     * @param prefix     需要匹配的前缀
     * @return 如果所有非空元素都以前缀开始返回true，否则返回false
     */
    public static boolean allStartsWithPrefix(String[] goodsNames, String prefix) {
        if (prefix == null || prefix.isEmpty()) {
            throw new IllegalArgumentException("Prefix must not be null or empty.");
        }

        for (String name : goodsNames) {
            // 去除前后空白字符，并检查是否为空或仅包含空白字符
            String trimmedName = (name != null) ? name.trim() : "";
            if (!trimmedName.startsWith(prefix)) {
                return false;
            }
        }
        return true;
    }

    public static double formatDouble(double d) {
        return (double) Math.round(d * 100) / 100;
    }

    public static boolean moneyComp(BigDecimal valueStr, BigDecimal compValueStr) {
        // 0:等于 >0:大于 <0:小于
        int result = valueStr.compareTo(compValueStr);
        return result >= 0;
    }

    @PostConstruct
    public void initSettingMap() {
        /*
          全国默认发成都，除了以下区域：
          1，浙江、江苏、上海、浙江、安徽（发杭州工厂）
          2，北京、天津、河北（发北京工厂）
          3，陕西、山西、河南、甘肃、宁夏（发西安工厂）
         */
        provinceMap.put("浙江省", "浙江省");
        provinceMap.put("江苏省", "浙江省");
        provinceMap.put("上海市", "浙江省");
        provinceMap.put("安徽省", "浙江省");

        provinceMap.put("北京市", "河北省");
        provinceMap.put("天津市", "河北省");
        provinceMap.put("河北省", "河北省");

        provinceMap.put("陕西省", "陕西省");
        provinceMap.put("山西省", "陕西省");
        provinceMap.put("河南省", "陕西省");
        provinceMap.put("甘肃省", "陕西省");
        provinceMap.put("宁夏省", "陕西省");

    }

    /**
     * 保存订单
     *
     * @param mobileOrder
     * @return X:小程序 D:抖音
     */
    public OrderPo process(MobileOrderDto mobileOrder, ShopPo shopPo, String prx, String goodId, List<DyPreOrderDto.ItemOrderInfoList> itemOrderInfoLists) {

        if (mobileOrder.getShopGoodsInfo() == null || mobileOrder.getShopGoodsInfo().isEmpty()) {
            throw new WashException("商品不存在");
        }
        // 计算价格
        BigDecimal orderPrice = BigDecimal.ZERO;
        int shoesNum = 0;
        StringBuilder builderGoodsName = new StringBuilder();
        List<ShopGoodsPo> shopGoodsPoList = new ArrayList<>(mobileOrder.getShopGoodsInfo().size());
        for (BuyGoodsDto buyGoodsDto : mobileOrder.getShopGoodsInfo()) {
            ShopGoodsPo shopGoodsPoPo = shopGoodsService.getById(buyGoodsDto.getShopGoodsId());
            shoesNum += shopGoodsPoPo.getShoesNum() * buyGoodsDto.getGoodsNum();
            orderPrice = orderPrice.add(
                    BigDecimal.valueOf(shopGoodsPoPo.getPrice()).multiply(BigDecimal.valueOf(buyGoodsDto.getGoodsNum())));
            builderGoodsName.append(shopGoodsPoPo.getName()).append(",");
            shopGoodsPoList.add(shopGoodsPoPo);
        }
        // 判断用户是否全部为补差价订单
        boolean isPriceDifference = isPriceDifferences(builderGoodsName);
        log.info("商品名称为 {}", builderGoodsName.toString());
        log.info("是否是补差价订单 {}", isPriceDifference);
        // 查询用户的信息
        CustomerPo customerPo = customerService.getById(mobileOrder.getCustomerId());
        if (customerPo == null) {
            throw new WashException("用户不存在");
        }
        // 如果这里没有店铺,就配置店铺
        if (shopPo == null) {
            ShopAndFactoryPair shopAndFactoryPair = getShopPo(mobileOrder, null, goodId);
            shopPo = shopAndFactoryPair.getShopPo();
        }
        String provincesName = null;
        String cityName = null;
        String countryName = null;
        if (Objects.isNull(shopPo)) {
            provincesName = mobileOrder.getProvinces();
            cityName = mobileOrder.getCity();
            // countryName=mobileOrder.getCountry();
        } else {
            /*
            List<String> infoList =
                AddressCuttingUtil.addressCutting(mobileOrder.getReceiveUserAddress().getReceiverAddress());*/
      /*      provincesName = mobileOrder.getProvinces();
            cityName = mobileOrder.getCity();*/
            provincesName = shopPo.getProvincesName();
            cityName = shopPo.getCityName();
            countryName = shopPo.getCountryName();
//            countryName = infoList.get(2);
        }

        // 根据店铺的省市区获取对应的工厂的收货地址
        String brandId = null;
        if (Objects.nonNull(shopPo)) {
            brandId = shopPo.getBrandId();
        }
        FactoryPo factoryPo =
                factoryAddressHelper.getFactoryAddressWithShopAddress(provincesName, cityName, countryName, brandId);
        // 检查物流地址检查
        String result = jdOrderService.preCheckAddress(mobileOrder.getReceiveUserAddress().getReceiverAddress(),
                /*shopPo.getAddress()*/factoryPo.getFactoryAddress());// 改成寄到这个店铺对应的工厂地址去
        log.info("地址检查的结果为: [{}]", result);
        if (!"success".equals(result)) {
            throw new WashException(result);
        }
        CustomerCouponPo customerCouponPo = null;
        BigDecimal totalPrice = orderPrice;
        if (StrUtil.isAllNotEmpty(mobileOrder.getUserCouponId())) {
            customerCouponPo = customerCouponService.getById(mobileOrder.getUserCouponId());
            if (customerCouponPo == null) {
                throw new WashException("优惠券不存在");
            }
            if (customerCouponPo.getStatus() != 0) {
                throw new WashException("优惠券已经使用或者过期");
            }
            CouponPo couponPo = couponService.getById(customerCouponPo.getCouponId());
            // 判断是不是满减卷 满减
            if (couponPo.getType() == 1 && customerCouponPo.getFullMoney() > orderPrice.doubleValue()) {
                throw new WashException("未达到满减要求");
            }

            totalPrice = totalPrice.subtract(BigDecimal.valueOf(customerCouponPo.getAmount()));
            // 判断两个值是否相等
            boolean isFlag = orderIsEqual(totalPrice, orderPrice);
            if (isPriceDifference) {
                // 判断是否使用优惠券:两个数值不相等的全部为补差价单子不能使用优惠券
                if (!isFlag) {
                    throw new WashException("补差价订单不能使用优惠券");
                }
            }
            // 至少需要付一分钱
            if (!moneyComp(totalPrice, BigDecimal.valueOf(0.01))) {
                throw new WashException("超出订单的最大的优惠金额");
            }
        }
        // 获取推广人的id,首先看看订单里面有没有推广人的id,订单没就用用户的,用户也没有就不用
        String inviteCusId = customerPo.getInviteCusId();
        if (StrUtil.isNotBlank(mobileOrder.getInviteCusId())) {
            inviteCusId = mobileOrder.getInviteCusId();
        }
        // 计算订单的信息
        OrderPo orderPo = new OrderPo();
        orderPo.setShopId(Objects.nonNull(shopPo) ? shopPo.getId() : mobileOrder.getShopId());
        orderPo.setCustomId(mobileOrder.getCustomerId());
        orderPo.setCustomPhone(customerPo.getPhone());
        orderPo.setBrandId(Objects.nonNull(shopPo) ? shopPo.getBrandId() : null);// 设置品牌id
        // 如果用户地址不存在，就用快递的地址
        if (StrUtil.isBlank(orderPo.getCustomPhone())) {
            orderPo.setCustomPhone(mobileOrder.getReceiveUserAddress().getReceiverMobile());
        }
        //目前抖音和小程序都是调用的这个方法,需要判断
        orderPo.setComeFrom("D".equals(prx) ? "3" : "4");
        orderPo.setShoeNum(shoesNum);
        orderPo.setTotalPrice(formatDouble(totalPrice.doubleValue()));
        orderPo.setOrderPrice(formatDouble(orderPrice.doubleValue()));
        orderPo.setDiscountRatio(formatDouble(orderPo.getTotalPrice() / orderPo.getOrderPrice()) * 100);
        orderPo.setStatus(OrderStatusEnum.PRE_PAY.getStatus());
        // 设置推广的用户的id
        if (StrUtil.isNotBlank(inviteCusId)) {
            orderPo.setInviteCusId(inviteCusId);
        }
        orderPo.setShoeCollectionDate(mobileOrder.getShoeCollectionDate());
        orderPo.setCustomerRemark(mobileOrder.getRemark());
        if (customerCouponPo != null) {
            orderPo.setMtOrderId(customerCouponPo.getCouponNo());
        }
        // 预约时间
        orderPo.setMtBeginTime(WashDateUtil.c1(mobileOrder.getShoeCollectionDate()));
        orderPo.setWashFactory(factoryPo.getFactoryName());
        orderPo.setFactoryId(factoryPo.getId());
        orderPo.setWashShop(shopPo.getShopName());
        if (isPriceDifference) {
            // 补差价订单已B开头
            orderPo.setOrderNo(CodeUtil.getOrderCodeNext("B", shopPo.getId(), shopPo.getShopCode()));
        } else {
            orderPo.setOrderNo(CodeUtil.getOrderCodeNext(prx, shopPo.getId(), shopPo.getShopCode()));
        }
        orderPo.setTransJson(JSONObject.toJSONString(mobileOrder));
        // orderPo.setShopId(shopPo.getId());
        orderPo.setShopGoodsUrl(shopGoodsPoList.get(0).getUrl());
        orderService.save(orderPo);
        List<OrderGoodPo> orderGoodPoList = new ArrayList<>();
        // 订单的商品添加
        for (int i = 0; i < shopGoodsPoList.size(); i++) {
            ShopGoodsPo shopGoodsPo = shopGoodsPoList.get(i);
            BuyGoodsDto buyGoodsDto = mobileOrder.getShopGoodsInfo().get(i);
            //处理抖音的，买多单会传多条数据过来,退的时候需要传多单给抖音退,不然只会退一个单的
            if (CollectionUtils.isNotEmpty(itemOrderInfoLists)) {
                for (DyPreOrderDto.ItemOrderInfoList itemOrderInfoList : itemOrderInfoLists) {
                    OrderGoodPo orderGoodPo = new OrderGoodPo();
                    orderGoodPo.setShopId(shopPo.getId());
                    orderGoodPo.setItemOrderId(itemOrderInfoList.getItem_order_id());
                    orderGoodPo.setName(shopGoodsPo.getName());
                    orderGoodPo.setPrice(shopGoodsPo.getPrice());
                    orderGoodPo.setBuyNum(1);
                    orderGoodPo.setGoodsId(shopGoodsPo.getId());
                    orderGoodPo.setShoesNum(shopGoodsPo.getShoesNum());
                    orderGoodPo.setWashType(shopGoodsPo.getWashType());
                    orderGoodPo.setOrderId(orderPo.getId());
                    orderGoodPo.setShopGoodsUrl(shopGoodsPo.getUrl());
                    orderGoodPo.setRemark("小程序的商品保存");
                    orderGoodPoList.add(orderGoodPo);
//                    orderGoodService.save(orderGoodPo);
                }
            } else {
                OrderGoodPo orderGoodPo = new OrderGoodPo();
                orderGoodPo.setShopId(shopPo.getId());
                orderGoodPo.setName(shopGoodsPo.getName());
                orderGoodPo.setPrice(shopGoodsPo.getPrice());
                orderGoodPo.setBuyNum(buyGoodsDto.getGoodsNum());
                orderGoodPo.setGoodsId(shopGoodsPo.getId());
                orderGoodPo.setShoesNum(shopGoodsPo.getShoesNum() * buyGoodsDto.getGoodsNum());
                orderGoodPo.setWashType(shopGoodsPo.getWashType());
                orderGoodPo.setOrderId(orderPo.getId());
                orderGoodPo.setShopGoodsUrl(shopGoodsPo.getUrl());
                orderGoodPo.setRemark("小程序的商品保存");
                orderGoodPoList.add(orderGoodPo);
//                orderGoodService.save(orderGoodPo);
            }
            orderGoodService.saveOrUpdateBatch(orderGoodPoList);
            log.info("保存订单的商品成功 {}", orderGoodPoList);
            // 销售数量+1
            shopGoodsPo.setSalesNum(shopGoodsPo.getSalesNum() + buyGoodsDto.getGoodsNum());
            shopGoodsService.updateById(shopGoodsPo);
        }

        // 使用优惠券
        if (customerCouponPo != null) {
            customerCouponPo.setStatus(1);
            customerCouponPo.setOrderId(orderPo.getId());
            customerCouponPo.setUserTime(DateUtil.now());
            customerCouponService.updateById(customerCouponPo);
        }
        // 处理需要分销信息,这里需要先检查订单里面有没有
        if (StrUtil.isNotBlank(inviteCusId)) {
            RegionDistributorPo distributorPo = regionDistributorService.getByUserId(inviteCusId);
            RegionTransactionDetailPo regionTransactionDetailPo = new RegionTransactionDetailPo();
            regionTransactionDetailPo.setType("1");
            regionTransactionDetailPo.setOrderId(orderPo.getId());
            regionTransactionDetailPo.setRecommendId(inviteCusId);
            regionTransactionDetailPo.setShareRatio(distributorPo.getShareRatio());
            regionTransactionDetailPo.setTotalPrice(orderPo.getTotalPrice());
            regionTransactionDetailPo
                    .setPromotionProfit(keepDecimals(orderPo.getTotalPrice() * distributorPo.getShareRatio() / 100));
            regionTransactionDetailPo.setStatus(0);
            regionTransactionDetailService.save(regionTransactionDetailPo);
        }
        return orderPo;
    }

    /**
     * @param mobileOrder
     * @return 获取下单的店铺地址
     */
    public ShopAndFactoryPair getShopPo(MobileOrderDto mobileOrder, String channel, String goodId) {
        ShopAndFactoryPair shopAndFactoryPair = new ShopAndFactoryPair();

        FactoryPo factoryPo = null;
        ShopPo shopPo = null;
        // 如果有商铺id，就根据商铺id
        /*   if (Objects.nonNull(*//*mobileOrder.getShopId()*//*HeaderUtil.getPoId())) {
            shopPo = shopService.getOne(new LambdaQueryWrapper<ShopPo>().eq(ShopPo::getPoId, HeaderUtil.getPoId()));
            if (shopPo == null) {
                throw new WashException(":该省暂未开放门店:" + mobileOrder.getShopId());
            }
            // 根据店铺的省市区获取对应的工厂的收货地址
            factoryPo = factoryAddressHelper.getFactoryAddressWithShopAddress(shopPo.getProvincesName(),
                shopPo.getCityName(), shopPo.getCountryName(),shopPo.getBrandId());
        } else {*/
        // 没有的话 需要按用户下单的省市区去找对应的工厂 TODO
        List<String> infoList =
                AddressCuttingUtil.addressCutting(mobileOrder.getReceiveUserAddress().getReceiverAddress());
        String shopProvince;
        // shop info，用户的省份映射到那个店铺 TODO
        shopProvince = infoList.get(0);
            /*  log.info("请求的地址是 [{}] 获取的shop为 [{}]", JSONObject.toJSONString(infoList),
                JSONObject.toJSONString(shopProvince));
            if (shopProvince == null) {
                shopProvince = "四川省";
            }*/
        shopProvince = mobileOrder.getProvinces().replace("省", "");
        String city = mobileOrder.getCity();
        //如果传了商品id就根据商品id去查询取对应的店铺
        if (StringUtils.isNotEmpty(goodId)) {
            //获取商品
            ShopGoodsPo shopGoodsPo = shopGoodsService.getById(goodId);
            if (shopGoodsPo == null) {
                throw new WashException(":该商品不存在:" + goodId);
            }
            //获取门店id
            ShopPo tempShopPo = shopService.getById(shopGoodsPo.getShopId());//通过商品取品牌id 然后根据品牌id和省市区+渠道去查询店铺
            shopPo = shopService.getOneShopByProvinces(shopProvince, city, channel, tempShopPo.getBrandId());
            if (Objects.isNull(shopPo)) {
                shopPo = shopService.getOneShopByProvinces(shopProvince, null, channel, tempShopPo.getBrandId());
            }
        } else {
            shopPo = shopService.getOneShopByProvinces(shopProvince, city, channel, null);
            if (Objects.isNull(shopPo)) {
                shopPo = shopService.getOneShopByProvinces(shopProvince, null, channel, null);
            }
        }
        if (shopPo == null) {
            throw new WashException(
                    shopProvince + ":该省暂未开放门店:" + mobileOrder.getReceiveUserAddress().getReceiverAddress());
        }
        // 根据店铺的省市区获取对应的工厂的收货地址
        factoryPo = factoryAddressHelper.getFactoryAddressWithShopAddress(/*infoList.get(0)*/shopProvince, /*infoList.get(1)*/city,
                /*infoList.get(2)*/null, shopPo.getBrandId());
//        }
        shopAndFactoryPair.setShopPo(shopPo);
        shopAndFactoryPair.setFactoryPo(factoryPo);
        return shopAndFactoryPair;
    }

    /**
     * 美团根据接收地址去匹配工厂数据
     *
     * @param address 接受地址
     * @return
     */
    public ShopAndFactoryPair getShopPoWithMt(String address) {
        ShopAndFactoryPair shopAndFactoryPair = new ShopAndFactoryPair();

        FactoryPo factoryPo = null;
        ;
        ShopPo shopPo = null;
        // 没有的话 需要按用户下单的省市区去找对应的工厂 TODO
        List<String> infoList = AddressCuttingUtil.addressCutting(address);
        String shopProvince;
        // shop info，用户的省份映射到那个店铺 TODO
        shopProvince = infoList.get(0);
        shopPo = shopService.getOneShopByProvinces(shopProvince, null, null, null
        );
        if (shopPo == null) {
            throw new WashException(shopProvince + ":该省暂未开放门店:" + address);
        }
        // 根据店铺的省市区获取对应的工厂的收货地址
        factoryPo =
                factoryAddressHelper.getFactoryAddressWithShopAddress(infoList.get(0), infoList.get(1), infoList.get(2), shopPo.getBrandId());
        shopAndFactoryPair.setShopPo(shopPo);
        shopAndFactoryPair.setFactoryPo(factoryPo);
        return shopAndFactoryPair;
    }

    /**
     * @param mobileOrder
     * @return 验证获取店铺
     */
    public ShopPo verifyGetShop(MobileOrderDto mobileOrder) {
        log.info("mobileOrder verifyGetShop: [{}]", JSONObject.toJSONString(mobileOrder));
        RegionWashShopVo regionWashShopVo = regionWashShopService.getLastProvince(mobileOrder.getProvinces());
        if (regionWashShopVo == null) {
            throw new WashException("区域【" + mobileOrder.getProvinces() + "】无门店,联系:15982021661");
        }
        ShopPo shopPo = shopService.getById(regionWashShopVo.getShopId());
        log.info("请求的省份是 [{}] 店铺为[{}]", mobileOrder.getProvinces(), shopPo.getShopName());
        return shopPo;
    }

    /**
     * 获取抖音的店铺
     *
     * @param poid 抖音门店的id
     * @return
     */
    public ShopPo getDyShopPo(String poid, String defaultPoid) {
        if (Objects.isNull(poid)) {
            poid = defaultPoid;//默认成都的poid
        }
        Assert.notNull(poid, "抖音门店id不能为空");
        ShopPo shopPo =
                shopService.getOne(new LambdaQueryWrapper<ShopPo>().eq(ShopPo::getPoId, poid).eq(ShopPo::getStatus, 1));
        if (Objects.isNull(shopPo) && StringUtils.isNotEmpty(defaultPoid)) {
            shopPo =
                    shopService.getOne(new LambdaQueryWrapper<ShopPo>().eq(ShopPo::getPoId, defaultPoid).eq(ShopPo::getStatus, 1));
        }
        Assert.notNull(shopPo, "抖音门店不存在.poid:" + poid);
        return shopPo;
    }

    /**
     * 保留两位小数 四舍五入
     *
     * @param doubleValue
     * @return
     */
    public Double keepDecimals(Double doubleValue) {
        BigDecimal value = BigDecimal.valueOf(doubleValue);
        BigDecimal bigDecimal = value.setScale(2, RoundingMode.HALF_UP);
        return bigDecimal.doubleValue();
    }

    /**
     * 判断订单是否相等
     *
     * @param totalPrice 优惠后的订单价格
     * @param orderPrice 原始订单价格
     * @return
     */
    private boolean orderIsEqual(BigDecimal totalPrice, BigDecimal orderPrice) {
        return totalPrice.compareTo(orderPrice) == 0;
    }

    /**
     * 判断是否为单独全部补差价订单
     *
     * @param builderGoodsName
     * @return
     */
    private boolean isPriceDifferences(StringBuilder builderGoodsName) {
        // 可能得商品名称格式为：
        // 补差价 1 元｜与客服沟通拍下,奢品鞋｜纯手工精洗1双｜免费上门取送
        // 奢品鞋｜纯手工精洗1双｜免费上门取送,皮质包包｜手工干洗 1 件｜免费上门取送
        // 补差价 1 元｜与客服沟通拍下,补差价 1 元｜与客服沟通拍下
        String[] goodsNames = builderGoodsName.toString().split(",");
        return allStartsWithPrefix(goodsNames, "补差价");
    }

}
